home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 9 / Example 9.3 / player.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-06-30  |  6.7 KB  |  265 lines

  1. #include "player.h"        
  2.  
  3. //Player Shaders
  4. SHADER lighting, teamCol;
  5. D3DXHANDLE worldHandle, viewProjHandle, sunHandle, teamColHandle, vertexCol;
  6. ID3DXLine *selLine = NULL;
  7.  
  8. void LoadPlayerResources(IDirect3DDevice9* Device)
  9. {
  10.     //Setup shaders
  11.     lighting.Init(Device, "shaders/lighting.vs", VERTEX_SHADER);
  12.     worldHandle = lighting.GetConstant("matW");
  13.     viewProjHandle = lighting.GetConstant("matVP");
  14.     sunHandle = lighting.GetConstant("DirToSun");
  15.     vertexCol = lighting.GetConstant("vertexCol");
  16.  
  17.     teamCol.Init(Device, "shaders/teamCol.ps", PIXEL_SHADER);
  18.     teamColHandle = teamCol.GetConstant("tmCol");
  19.  
  20.     //Line for unit selection
  21.     D3DXCreateLine(Device, &selLine);
  22. }
  23.  
  24. void UnloadPlayerResources()
  25. {
  26.     if(selLine != NULL)
  27.         selLine->Release();
  28.     selLine = NULL;
  29. }
  30.  
  31. //////////////////////////////////////////////////////////////////////////////////
  32. //                                PLAYER                                            //
  33. //////////////////////////////////////////////////////////////////////////////////
  34.  
  35. PLAYER::PLAYER(int _teamNo, D3DXVECTOR4 _teamCol, INTPOINT startPos, TERRAIN* _terrain, IDirect3DDevice9* _Device)
  36. {
  37.     m_teamNo = _teamNo;
  38.     m_teamColor = _teamCol;
  39.     m_pTerrain = _terrain;
  40.     m_pDevice = _Device;
  41.     m_areaSelect = false;
  42.  
  43.     if(m_pTerrain == NULL)return;
  44.  
  45.     //Add a few buildings
  46.     for(int i=0;i<3;i++)
  47.     {
  48.         INTPOINT p = FindClosestBuildingLocation(i, startPos);
  49.  
  50.         if(m_pTerrain->Within(p))
  51.             AddMapObject(i, p, true);
  52.     }
  53.  
  54.     //Also add a few units
  55.     for(int i=0;i<6;i++)
  56.     {
  57.         INTPOINT mp;
  58.         bool ok = false;
  59.         do
  60.         {
  61.             mp.x = rand()%20 - 10 + startPos.x;
  62.             mp.y = rand()%20 - 10 + startPos.y;
  63.  
  64.             MAPTILE *tile = m_pTerrain->GetTile(mp);
  65.             if(tile != NULL)ok = tile->m_walkable && tile->m_pMapObject == NULL;
  66.         }
  67.         while(!ok);
  68.  
  69.         AddMapObject(i % 3, mp, false);
  70.     }
  71. }
  72.  
  73. PLAYER::~PLAYER()
  74. {
  75.     for(int i=0;i<m_mapObjects.size();i++)
  76.         if(m_mapObjects[i] != NULL)
  77.             delete m_mapObjects[i];
  78. }
  79.  
  80. void PLAYER::AddMapObject(int type, INTPOINT mp, bool isBuilding)
  81. {
  82.     if(isBuilding)
  83.         m_mapObjects.push_back(new BUILDING(type, m_teamNo, mp, m_pTerrain, true, m_pDevice));
  84.     else m_mapObjects.push_back(new UNIT(type, m_teamNo, mp, m_pTerrain, m_pDevice));
  85. }
  86.  
  87. void PLAYER::RenderMapObjects(CAMERA &camera)
  88. {
  89.     D3DXMATRIX identity;
  90.     D3DXMatrixIdentity(&identity);
  91.     
  92.     lighting.SetMatrix(viewProjHandle, camera.GetViewMatrix() * camera.GetProjectionMatrix());
  93.  
  94.     //Sun direction
  95.     D3DXVECTOR3 sun;
  96.     D3DXVec3Normalize(&sun, &D3DXVECTOR3(0.5f, 1.0f, -0.5));
  97.     lighting.SetVector3(sunHandle, sun);
  98.  
  99.     //Team color
  100.     teamCol.SetVector4(teamColHandle, m_teamColor);
  101.  
  102.     //Vertex color
  103.     lighting.SetVector4(vertexCol, D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f));
  104.  
  105.     lighting.Begin();
  106.     teamCol.Begin();
  107.  
  108.     //Render units
  109.     for(int i=0;i<m_mapObjects.size();i++)
  110.         if(m_mapObjects[i] != NULL)
  111.             if(!camera.Cull(m_mapObjects[i]->GetBoundingBox()))
  112.             {
  113.                 if(m_mapObjects[i]->m_isBuilding)
  114.                     lighting.SetMatrix(worldHandle, m_mapObjects[i]->GetWorldMatrix());
  115.                 else lighting.SetMatrix(worldHandle, identity);
  116.  
  117.                 m_mapObjects[i]->Render();
  118.             }
  119.  
  120.     teamCol.End();
  121.     lighting.End();
  122. }
  123.  
  124. void PLAYER::PaintSelectedMapObjects(CAMERA &camera)
  125. {
  126.     //Paint selected map objects
  127.     for(int i=0;i<m_mapObjects.size();i++)
  128.         if(m_mapObjects[i] != NULL)
  129.             if(!camera.Cull(m_mapObjects[i]->GetBoundingBox()))
  130.                 m_mapObjects[i]->PaintSelected();
  131. }
  132.  
  133. void PLAYER::UpdateMapObjects(float deltaTime)
  134. {
  135.     for(int i=0;i<m_mapObjects.size();i++)
  136.         if(m_mapObjects[i] != NULL)
  137.             m_mapObjects[i]->Update(deltaTime);
  138. }
  139.  
  140. INTPOINT PLAYER::FindClosestBuildingLocation(int buildType, INTPOINT mp)
  141. {
  142.     //i = Search Radius
  143.     for(int i=0;i<30;i++)
  144.     {
  145.         for(int x=mp.x - i;x<=mp.x + i;x++)
  146.         {
  147.             if(PlaceOk(buildType, INTPOINT(x, mp.y - i), m_pTerrain))return INTPOINT(x, mp.y - i);
  148.             if(PlaceOk(buildType, INTPOINT(x, mp.y + i), m_pTerrain))return INTPOINT(x, mp.y + i);
  149.         }
  150.  
  151.         for(int y=mp.y - i;y<=mp.y + i;y++)
  152.         {
  153.             if(PlaceOk(buildType, INTPOINT(mp.x - i, y), m_pTerrain))return INTPOINT(mp.x - i, y);
  154.             if(PlaceOk(buildType, INTPOINT(mp.x + i, y), m_pTerrain))return INTPOINT(mp.x + i, y);
  155.         }
  156.     }
  157.  
  158.     //No good place found
  159.     return INTPOINT(-1, -1);
  160. }
  161.  
  162. void PLAYER::Select(MOUSE &mouse)
  163. {
  164.     try
  165.     {
  166.         if(mouse.ClickLeft())    // If the mouse button is pressed
  167.         {                
  168.             for(int i=0;i<m_mapObjects.size();i++)    //Deselect all m_mapObjects
  169.                 m_mapObjects[i]->m_selected = false;
  170.  
  171.             if(!m_areaSelect)        // If no area selection is in progress
  172.             {    
  173.                 //Find closest m_mapObjects
  174.                 int mapObject = -1;
  175.                 float bestDist = 100000.0f;
  176.  
  177.                 D3DXMATRIX world;
  178.                 D3DXMatrixIdentity(&world);
  179.                 m_pDevice->SetTransform(D3DTS_WORLD, &world);
  180.                 RAY ray = mouse.GetRay();
  181.  
  182.                 for(int i=0;i<m_mapObjects.size();i++)
  183.                 {                    
  184.                     float dist = ray.Intersect(m_mapObjects[i]->GetBoundingBox());
  185.  
  186.                     if(dist >= 0.0f && dist < bestDist)
  187.                     {
  188.                         mapObject = i;
  189.                         bestDist = dist;
  190.                     }
  191.                 }
  192.                 if(mapObject > -1)
  193.                     m_mapObjects[mapObject]->m_selected = true;
  194.                 else
  195.                 {
  196.                     m_areaSelect = true;        // if no unit if found,                                             
  197.                     m_startSel = mouse;        // start area selection
  198.                 }
  199.             }
  200.             else    //Area Selection in progress
  201.             {
  202.                 // Create area rectangle
  203.                 INTPOINT p1 = m_startSel, p2 = mouse;
  204.                 if(p1.x > p2.x){int temp = p2.x;p2.x = p1.x;p1.x = temp;}
  205.                 if(p1.y > p2.y){int temp = p2.y;p2.y = p1.y;p1.y = temp;}
  206.                 RECT selRect = {p1.x, p1.y, p2.x, p2.y};
  207.  
  208.                 //Draw selection rectangle
  209.                 D3DXVECTOR2 box[] = {D3DXVECTOR2(p1.x, p1.y), D3DXVECTOR2(p2.x, p1.y), 
  210.                                      D3DXVECTOR2(p2.x, p2.y), D3DXVECTOR2(p1.x, p2.y), 
  211.                                      D3DXVECTOR2(p1.x, p1.y)};
  212.  
  213.                 selLine->SetWidth(1.0f);
  214.                 selLine->Begin();
  215.                 selLine->Draw(box, 5, 0xffffffff);                
  216.                 selLine->End();
  217.  
  218.                 //Select any units inside our rectangle
  219.                 for(int i=0;i<m_mapObjects.size();i++)
  220.                     if(m_mapObjects[i] != NULL && !m_mapObjects[i]->m_isBuilding)
  221.                     {
  222.                         INTPOINT p = GetScreenPos(m_mapObjects[i]->m_position, m_pDevice);
  223.                         if(p.inRect(selRect))m_mapObjects[i]->m_selected = true;
  224.                     }
  225.             }
  226.         }
  227.         else if(m_areaSelect)        //Stop area selection
  228.             m_areaSelect = false;
  229.  
  230.     }
  231.     catch(...)
  232.     {
  233.         debug.Print("Error in PLAYER::Select()");
  234.     }
  235. }
  236.  
  237. void PLAYER::UnitOrders(MOUSE &mouse)
  238. {
  239.     if(mouse.ClickRight())
  240.     {
  241.         mouse.DisableInput(300);
  242.  
  243.         for(int i=0;i<m_mapObjects.size();i++)
  244.             if(m_mapObjects[i] != NULL)
  245.                 if(!m_mapObjects[i]->m_isBuilding && m_mapObjects[i]->m_selected)
  246.                 {
  247.                     //Cast to UNIT
  248.                     UNIT *unit = (UNIT*)m_mapObjects[i];
  249.                     unit->Goto(mouse.m_mappos, false, true);
  250.                 }
  251.     }
  252. }
  253.  
  254. INTPOINT PLAYER::GetCenter()
  255. {
  256.     INTPOINT p;
  257.  
  258.     for(int i=0;i<m_mapObjects.size();i++)
  259.         if(m_mapObjects[i] != NULL)
  260.             p += m_mapObjects[i]->m_mappos;
  261.  
  262.     p /= m_mapObjects.size();
  263.  
  264.     return p;
  265. }